Release the outbound recycle guard on local-input EOF - #31
Merged
Conversation
Fixes the Linux defect the diagnostics branch located, and corrects the reasoning I got wrong the first time. The guard was released when the whole attach returned. On Linux that attach can stay up long after the local side is finished: the forced trace measured released=false at 40001ms with the SERVER still reporting srv_active_attaches=1 and srv_detached=0, where macOS detaches the same sequence in under 300ms. So the guard pinned the endpoint for the whole stall and endpoint repair became impossible on exactly the hosts we were about to deploy to. That is worse than the disruption the guard was added to prevent. The guard is now released when the local INPUT side reaches EOF. What I must not claim, and did claim in my first proposal, is that no user remains at that point: a client can half-close its input and go on reading output. So only the recycle guard is released. The session, its buffering and its replay are untouched, and a half-closed reader keeps receiving remote output across the recycle that releasing allowed. The guard now lives on the session rather than in the attach's stack frame, so whichever comes first releases it: local-input EOF, or the attach ending. Nothing is held between attaches, which is what keeps a reconnecting session from blocking the very recycle that might let it reconnect. Proofs, each checked against a control: - A live bidirectional local client still blocks the recycle. - Local-input EOF releases the guard within 500ms. The bound is load-bearing on purpose: the queued remote command sleeps a second before printing, so a release inside that window can only come from local-input EOF. With a generous timeout instead, the test passed even with the fix reverted, because macOS tears down in ~300ms and the two paths were indistinguishable. That is the third time in this work a no-change assertion needed a control to be worth anything. - A half-closed reader receives the delayed output exactly once across the now-allowed recycle: counted, not merely sighted, so a duplicate would fail. - A reconnecting session does not block the recycle; proven by stopping the peer so the session is genuinely between attaches rather than racily so. The underlying Linux teardown latency is NOT addressed here and is being filed separately with the trace. Gates, macOS: shell 12, lib 173, provisioning 10, sync_slice 3, local_slice 21.
… EOF PR 31's first commit fixed the clean-EOF case and left the Linux CI failure exactly as it was, because the case that fails there is the other one. run_local_reader propagated a read error with ? and returned before reaching mark_send_closed, so an abrupt local close never released the recycle guard. Dropping a local socket yields a clean zero-length read on macOS and an error on Linux, which is why this was invisible locally and why my first fix looked complete while changing nothing about the failing test. Only the guard is released on that path. send_closed and every other teardown semantic stay as they were: an error path is not where I want to be changing session lifecycle, and the underlying Linux teardown latency is filed separately.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the Linux defect located by draft PR #30's diagnostics: the outbound recycle guard was pinned for as long as the attach lived, and on Linux that outlasted the local side by more than 40s with the server still reporting the session attached, so endpoint repair became impossible.
The guard is now released on local-input EOF. Only the guard — the session, its buffering and its replay are untouched, because a half-closed client can still be reading output.
Proofs (each verified against a control that fails without the fix): live bidirectional client still blocks; local-input EOF releases within a bound that is load-bearing because the queued remote work takes longer than it; a half-closed reader receives delayed output exactly once across the now-allowed recycle; a reconnecting session does not block.
The underlying Linux teardown latency is deliberately out of scope and filed separately.